package com.javatip.common.utils;

import java.io.*;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 54716
 * @DATE 2024/5/25 11:58
 * 利用java执行.py文件
 */
public class RunPythonScript {

    // 用于存储 Python 脚本进程的映射
    private static final Map<String, Process> processMap = new ConcurrentHashMap<>();


    public static void runCommand(String command) {
        try {
            // 构建Python脚本执行命令
            ProcessBuilder pb = new ProcessBuilder("python", command);
            pb.redirectErrorStream(true); // 将错误输出合并到标准输出流

            // 启动进程并执行Python脚本
            Process process = pb.start();

            // 读取Python脚本的输出
            InputStream inputStream = process.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }

            // 等待Python脚本执行完成
            int exitCode = process.waitFor();
            System.out.println("Done, exitcode is " + exitCode);

        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    // 启动 Python 脚本并返回进程状态代码


    public static int runCommandWithPara(String command, String model, String dataset, int batchSize, int epoch, int earlyStop, double lr) {
        String taskId = model + "-" + dataset;
        Process process = null;

        try {
            // 构建 Python 脚本执行命令
            ProcessBuilder pb = new ProcessBuilder("python", command, model, dataset, String.valueOf(batchSize), String.valueOf(epoch), String.valueOf(earlyStop), String.valueOf(lr));
            System.out.println("command: " + "python " + command + " " + model + " " + dataset + " " + batchSize + " " + epoch + " " + earlyStop + " " + lr);
            pb.redirectErrorStream(true); // 将错误输出合并到标准输出流

            // 启动进程并执行 Python 脚本
            process = pb.start();
            processMap.put(taskId, process); // 保存进程引用到 Map 中

            // 读取 Python 脚本的输出
            Process finalProcess = process; // 为了在内部类中使用
            new Thread(() -> {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(finalProcess.getInputStream()))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        System.out.println(line);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();

            // 等待 Python 脚本执行完成
            int exitCode = process.waitFor();
            System.out.println("Done, exit code is " + exitCode);
            return exitCode;

        } catch (Exception e) {
            e.printStackTrace();
            return 1; // 出现异常时返回 1
        } finally {
            if (process != null) {
                processMap.remove(taskId); // 从 Map 中移除
            }
        }
    }

    // 用于调用 Python 脚本并传递参数
    public static void runPythonScriptWithGeoArgs(String pythonScriptPath, String pngFolderPath, String tifFolderPath, String shapefileFolderPath) {
        try {
            // 构建命令行
            String command = "python " + pythonScriptPath + " --png_folder " + pngFolderPath + " --tif_folder " + tifFolderPath + " --shapefile_folder " + shapefileFolderPath;
            System.out.println("runPythonScriptWithGeoArgs command: " + command);

            // 创建 ProcessBuilder 来运行命令
            ProcessBuilder processBuilder = new ProcessBuilder(command.split(" "));

            // 启动 Python 脚本进程
            Process process = processBuilder.start();

            // 读取 Python 脚本的输出流，使用新线程来处理
            Process finalProcess = process; // 为了在内部类中使用
            new Thread(() -> {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(finalProcess.getInputStream()))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        System.out.println(line);  // 打印 Python 脚本的输出
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();

            // 等待 Python 脚本执行完成并返回退出码
            int exitCode = process.waitFor();
            System.out.println("Python script finished with exit code: " + exitCode);

            // 将进程加入映射表（如果需要跟踪进程）
            processMap.put(pythonScriptPath, process);

        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    // 启动 Python 脚本并返回进程状态代码，修改方法签名，使其返回 Process 对象
    public static Process runCommandWithParaProcess(String scriptPath, int id, String model, int modeUserlId, String dataset, String datasetTrain, String modelName, String datasetVal, int batchSize, int minEpoch, int epoch, int earlyStop, double lr, Integer modelId, int imageSize, int InputChan, int outChan,String exceptionRecordPath) {
        Process process = null;
        try {
            // 使用 ProcessBuilder 启动进程
            ProcessBuilder pb = new ProcessBuilder("python", scriptPath, String.valueOf(id), model, String.valueOf(modeUserlId), dataset, datasetTrain, modelName, datasetVal, String.valueOf(batchSize), String.valueOf(minEpoch), String.valueOf(epoch), String.valueOf(earlyStop), String.valueOf(lr), String.valueOf(modelId),String.valueOf(imageSize),String.valueOf(InputChan),String.valueOf(outChan));
            pb.redirectErrorStream(true); // 合并标准输出和标准错误
            process = pb.start();

            // 保存输出到 StringBuilder 中
            StringBuilder output = new StringBuilder();

            // 读取 Python 脚本的输出
            Process finalProcess = process; // 为了在内部类中使用
            new Thread(() -> {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(finalProcess.getInputStream()))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        System.out.println(line);
                        output.append(line).append(System.lineSeparator());
                    }
                    // 在所有行都读取完后再写入文件
                    try (FileWriter writer = new FileWriter(exceptionRecordPath)) {
                        writer.write(output.toString());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    output.append(e.getMessage()).append(System.lineSeparator());
                }
            }).start();

            System.out.println("Python 脚本已启动");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return process;
    }

    // 启动 Python 脚本并返回进程状态代码，修改方法签名，使其返回 Process 对象
    public static Process ChangeRunCommandWithParaProcess(
            String scriptPath,
            int id,
            String modelName,
            int modeUserlId,
            String datasetTrainLoc,
            String datasetTrain,


            String datasetValLoc,
            String datasetVal,


            int batchSize,
            int minEpoch,
            int epoch,
            int earlyStop,
            double lr,
            Integer modelId,
            int imageSize,
            int InputChan,
            int outChan,
            String exceptionRecordPath) {

        Process process = null;
        try {
            // 使用 ProcessBuilder 启动进程
            ProcessBuilder pb = new ProcessBuilder("python", scriptPath, String.valueOf(id), modelName, String.valueOf(modeUserlId),datasetTrainLoc, datasetTrain,datasetValLoc, datasetVal,String.valueOf(batchSize), String.valueOf(minEpoch), String.valueOf(epoch), String.valueOf(earlyStop), String.valueOf(lr), String.valueOf(modelId),String.valueOf(imageSize),String.valueOf(InputChan),String.valueOf(outChan));
            pb.redirectErrorStream(true); // 合并标准输出和标准错误
            process = pb.start();

            // 保存输出到 StringBuilder 中
            StringBuilder output = new StringBuilder();

            // 读取 Python 脚本的输出
            Process finalProcess = process; // 为了在内部类中使用
            new Thread(() -> {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(finalProcess.getInputStream()))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        System.out.println(line);
                        output.append(line).append(System.lineSeparator());
                    }
                    // 在所有行都读取完后再写入文件
                    try (FileWriter writer = new FileWriter(exceptionRecordPath)) {
                        writer.write(output.toString());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    output.append(e.getMessage()).append(System.lineSeparator());
                }
            }).start();

            System.out.println("Python 脚本已启动");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return process;
    }

    // 终止正在运行的 Python 脚本
    public static void stopPythonScript(String model, String dataset) {
        String taskId = model + "-" + dataset;
        Process process = processMap.get(taskId);
        if (process != null) {
            process.destroy(); // 终止进程
            processMap.remove(taskId); // 从 Map 中移除
        }
    }

    /*
        单一目标检测训练
     */
    public static void startSingleDectionTraining(String scriptPath,
                                                  int id,
                                                  String modelName,
                                                  String dataset,
                                                  String datasetTrain,
                                                  String datasetVal,
                                                  int batchSize,
                                                  int minEpoch,
                                                  int epoch,
                                                  int earlyStop,
                                                  double lr,
                                                  Integer modelId,
                                                  String exceptionRecordPath
                                                  )
    {
        Process process = null;
        try {

        }catch(Exception e){
            }
    }



    public static void main(String[] args) {
    }
}
